﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using Sharp.Domain.Repositories;

#endregion

namespace Sharp.Domain.PlatformBoundedContext
{
    public partial class EntityFrameworkRepositoryContext : RepositoryContext, ISql
    {
        private readonly ThreadLocal<Entities> _localCtx = new ThreadLocal<Entities>(() => new Entities());

        public override void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj)
        {
            _localCtx.Value.Set<TAggregateRoot>().Remove(obj);
            Committed = false;
        }

        public override void RegisterModified<TAggregateRoot>(TAggregateRoot obj)
        {
            //_localCtx.Value.Entry<TAggregateRoot>(obj).State = EntityState.Modified;
            Committed = false;
        }

        public override void RegisterNew<TAggregateRoot>(TAggregateRoot obj)
        {
            _localCtx.Value.Set<TAggregateRoot>().Add(obj);

            Committed = false;
        }

        public override void ApplyCurrentValues<TAggregateRoot>(TAggregateRoot original, TAggregateRoot current)
        {
            _localCtx.Value.Entry(original).CurrentValues.SetValues(current);
            Committed = false;
        }


        #region 提交更改
        /// <summary>
        /// 提交更改
        /// </summary>
        public override void Commit()
        {
            if (!Committed)
            {
                try
                {
                    _localCtx.Value.SaveChanges();
                }
                catch (DbUpdateException ex)
                {
                    Exception innerException = ex.InnerException;
                    while (innerException != null)
                    {
                        if (innerException.InnerException != null)
                            innerException = innerException.InnerException;
                        else
                            throw new Exception(innerException.Message);
                    }

                }
                catch (DbEntityValidationException ex)
                {
#if DEBUG

                    var dbEntityValidationResults = ex.EntityValidationErrors as DbEntityValidationResult[] ??
                                                    ex.EntityValidationErrors.ToArray();
                    StringBuilder sberr = new StringBuilder();
                    foreach (var item in dbEntityValidationResults)
                    {
                        sberr.AppendLine(item.Entry.Entity + "有错误");
                        foreach (var err in item.ValidationErrors)
                        {
                            sberr.AppendFormat("\t\t{0}:{1}\r\n", err.PropertyName, err.ErrorMessage);
                        }
                    }
                    Debug.WriteLine(sberr.ToString(), "数据库操作失败");
                    throw new Exception(sberr.ToString());
#endif
                    throw;
                }
                catch
                {
                    throw;
                }
                Committed = true;
            }
        }
        #endregion

        public override void Rollback()
        {
            Committed = false;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!Committed)
                    Commit();
                _localCtx.Value.Dispose();
                _localCtx.Dispose();
                base.Dispose(disposing);
            }
        }


        public DbContext Context
        {
            get { return _localCtx.Value; }
        }

        public IEnumerable<TAggregateRoot> ExecuteQuery<TAggregateRoot>(string sqlQuery, params object[] parameters)
        {
            return _localCtx.Value.Database.SqlQuery<TAggregateRoot>(sqlQuery, parameters);
        }

        public int ExecuteCommand(string sqlCommand, params object[] parameters)
        {
            return _localCtx.Value.Database.ExecuteSqlCommand(sqlCommand, parameters);
        }
    }
}